﻿using System;
using System.Collections.Generic;
using System.Linq;

using System.Data;
using Prodma.DataAccess.Database;
using Prodma.DataAccess.Interfaces.Models;
using Prodma.DataAccess.Models.ViewModels;
using Prodma.DataAccess.Repositories;
using Prodma.DataAccess.Helper.Enumerators;

namespace Prodma.DataAccess.DataService
{
    public class ArchiveService : IArchiveRepository
    {

        private DataContext context = new DataContext();


        #region IArchiveRepository Members

        public IList<int> GetProjectList()
        {
            DataContext context = new DataContext();
            using (context)
            {
                var list = (from archive in context.tb_Archive
                            group archive by archive.tb_Project.Id into project
                            select project.Key).ToList();

                return list;
            }
        }
        #endregion

        #region IRecordOperation<tb_Archive,ArchiveVm> Members

        public IList<ArchiveVm> GetList()
        {
            DataContext context = new DataContext();
            using (context)
            {
                var list = (from archive in context.tb_Archive
                            join order in context.tb_ArchiveOrder
                                on archive.Id equals order.Archive
                            select new ArchiveVm
                            {
                                Id = archive.Id,
                                Name = archive.Name,
                                Title = archive.Title,
                                IsLive = archive.IsLive,
                                Order = new ArchiveOrderVm() { OrderNo = order.OrderNo },
                                Project = new ProjectVm() { Id = archive.tb_Project.Id, Name = archive.tb_Project.Name },
                                State = new StateVm() { Id = archive.tb_State.Id, Name = archive.tb_State.Name }
                            }).OrderByDescending(x => x.Order.OrderNo).ToList();

                return list;
            }
        }
        public void New(tb_Archive entity)
        {
            DataContext context = new DataContext();
            using (context)
            {
                context.AddTotb_Archive(entity);
                context.SaveChanges();
            }
        }
        public ArchiveVm Edit(int id)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var edit = (from archive in context.tb_Archive
                            where archive.Id == id
                            select new ArchiveVm
                            {
                                Id = archive.Id,
                                Name = archive.Name,
                                Title = archive.Title,
                                Folder = archive.Folder,
                                IsLive = archive.IsLive,
                                Project = new ProjectVm() { Id = archive.tb_Project.Id, Name = archive.tb_Project.Name },
                                State = new StateVm() { Id = archive.tb_State.Id }
                            }).FirstOrDefault();

                return edit;
            }
        }
        public void Update(int id, tb_Archive entity)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var edit = (from archive in context.tb_Archive
                            where archive.Id == id
                            select archive).FirstOrDefault();

                edit.Name = entity.Name;
                edit.Title = entity.Title;
                edit.Folder = entity.Folder;
                edit.IsLive = entity.IsLive;
                edit.tb_ProjectReference.EntityKey = entity.tb_ProjectReference.EntityKey;
                edit.tb_StateReference.EntityKey = entity.tb_StateReference.EntityKey;

                context.SaveChanges();
            }
        }
        public void Delete(int id)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var delete = (from archive in context.tb_Archive
                              where archive.Id == id
                              select archive).FirstOrDefault();

                context.DeleteObject(delete);
                context.SaveChanges();
            }
        }
        #endregion

        #region IFindOperation<ArchiveVm> Members

        public IList<ArchiveVm> GetList(Dictionary<string, string> find)
        {
            string findName = find["name"];
            DataContext context = new DataContext();
            using (context)
            {
                var list = (from archive in context.tb_Archive
                            join order in context.tb_ArchiveOrder
                                on archive.Id equals order.Archive
                            where archive.Name.StartsWith(findName)
                            select new ArchiveVm()
                            {
                                Id = archive.Id,
                                Name = archive.Name,
                                Title = archive.Title,
                                IsLive = archive.IsLive,
                                Order = new ArchiveOrderVm() { OrderNo = order.OrderNo },
                                Project = new ProjectVm() { Id = archive.tb_Project.Id, Name = archive.tb_Project.Name },
                                State = new StateVm() { Id = archive.tb_State.Id, Name = archive.tb_State.Name }
                            }).OrderByDescending(x => x.Order.OrderNo).ToList();

                return list;
            }
        }
        #endregion

        #region IParentRelationshipOperation Members

        public IList<int> GetCounts()
        {
            DataContext context = new DataContext();
            using (context)
            {
                var countList = (from archive in context.tb_Archive
                                 group archive by archive.tb_Project.Id into project
                                 select project.Count()).ToList();

                return countList;
            }
        }
        public IList<int> GetCounts(string find)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var countList = (from archive in context.tb_Archive
                                 where archive.Name.StartsWith(find)
                                 group archive by archive.tb_Project.Id into project
                                 select project.Count()).ToList();

                return countList;
            }
        }
        #endregion

        #region IRowCountOperation Members

        public int GetTotalRowCount()
        {
            DataContext context = new DataContext();
            using (context)
            {
                int rowCount = (from archive in context.tb_Archive
                                select archive).Count();

                return rowCount;
            }
        }
        public int GetTotalRowCount(Dictionary<string, string> find)
        {
            string findName = find["name"];
            DataContext context = new DataContext();
            using (context)
            {
                int rowCount = (from archive in context.tb_Archive
                                where archive.Name.StartsWith(findName)
                                select archive).Count();

                return rowCount;
            }
        }
        #endregion

        #region IOrderOperation<ArchiveOrderVm> Members

        public void OrderUp(int id, ArchiveOrderVm viewModel)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var currentOrder = (from order in context.tb_ArchiveOrder
                                    where order.Archive == viewModel.Archive &&
                                          order.tb_Project.Id == viewModel.Project &&
                                          order.OrderNo == viewModel.OrderNo
                                    select order).FirstOrDefault();
                var nextOrder = (from order in context.tb_ArchiveOrder
                                 where order.OrderNo > viewModel.OrderNo &&
                                       order.tb_Project.Id == viewModel.Project
                                 select order).OrderBy(x => x.OrderNo).FirstOrDefault();

                if (nextOrder != null)
                {
                    nextOrder.OrderNo--;
                    currentOrder.OrderNo++;
                }

                context.SaveChanges();
            }
        }
        public void OrderDown(int id, ArchiveOrderVm viewModel)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var currentOrder = (from order in context.tb_ArchiveOrder
                                    where order.Archive == viewModel.Archive &&
                                          order.tb_Project.Id == viewModel.Project &&
                                          order.OrderNo == viewModel.OrderNo
                                    select order).FirstOrDefault();

                var previousOrder = (from order in context.tb_ArchiveOrder
                                     where order.OrderNo < viewModel.OrderNo &&
                                           order.tb_Project.Id == viewModel.Project
                                     select order).OrderByDescending(x => x.OrderNo).FirstOrDefault();

                if (previousOrder != null)
                {
                    previousOrder.OrderNo++;
                    currentOrder.OrderNo--;
                }

                context.SaveChanges();
            }
        }
        public void SetOrder(int id, ArchiveOrderVm viewModel)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var lastOrder = (from order in context.tb_ArchiveOrder
                                 where order.tb_Project.Id == viewModel.Project
                                 select order).OrderByDescending(x => x.OrderNo).Take(1).FirstOrDefault();

                if (viewModel.SetOrderNo > lastOrder.OrderNo || viewModel.SetOrderNo <= 0)
                {
                    return;
                }

                var currentOrder = (from order in context.tb_ArchiveOrder
                                    where order.Archive == viewModel.Archive &&
                                          order.tb_Project.Id == viewModel.Project &&
                                          order.OrderNo == viewModel.OrderNo
                                    select order).FirstOrDefault();

                int setOrderNo = (lastOrder.OrderNo - viewModel.SetOrderNo) + 1;
                int fark = setOrderNo - currentOrder.OrderNo;
                int oldCurrentOrder = currentOrder.OrderNo;
                currentOrder.OrderNo = setOrderNo;

                if (fark > 0)
                {
                    var nextOrder = (from order in context.tb_ArchiveOrder
                                     where order.OrderNo > oldCurrentOrder &&
                                           order.OrderNo <= setOrderNo &&
                                           order.tb_Project.Id == viewModel.Project
                                     select order).OrderBy(x => x.OrderNo).ToList();

                    foreach (tb_ArchiveOrder m in nextOrder)
                    {
                        m.OrderNo--;
                        context.SaveChanges();
                    }
                }
                else if (fark <= 0)
                {
                    var previousOrder = (from order in context.tb_ArchiveOrder
                                         where order.OrderNo < oldCurrentOrder &&
                                               order.OrderNo >= setOrderNo &&
                                               order.tb_Project.Id == viewModel.Project
                                         select order).OrderBy(x => x.OrderNo).ToList();

                    foreach (tb_ArchiveOrder m in previousOrder)
                    {
                        m.OrderNo++;
                        context.SaveChanges();
                    }
                }

                context.SaveChanges();
            }
        }
        #endregion

        #region IStateOperation Members

        public void SetActive(int id)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var state = (from archive in context.tb_Archive
                             where archive.Id == id
                             select archive).FirstOrDefault();

                state.tb_StateReference.EntityKey = new EntityKey("DataContext.tb_State", "Id", Convert.ToInt32(State.Active));

                context.SaveChanges();
            }
        }
        public void SetPassive(int id)
        {
            DataContext context = new DataContext();
            using (context)
            {
                var state = (from archive in context.tb_Archive
                             where archive.Id == id
                             select archive).FirstOrDefault();

                state.tb_StateReference.EntityKey = new EntityKey("DataContext.tb_State", "Id", Convert.ToInt32(State.Passive));

                context.SaveChanges();
            }
        }
        #endregion

    }
}
